import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import svgLoader from "vite-svg-loader";
import removeConsole from "vite-plugin-remove-console";
import viteCompression from "vite-plugin-compression";

import { defineConfig, loadEnv } from "vite";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
import {
  name,
  version,
  engines,
  dependencies,
  devDependencies
} from "./package.json";

/** @type {import('vite').UserConfig} */
export default defineConfig(({ mode }) => {
  const root = process.cwd();
  const alias = {
    "@": pathResolve("../src")
  };
  const { VITE_PORT, VITE_HOST_URL, VITE_PUBLIC_PATH } = wrapperEnv(
    loadEnv(mode, root)
  );
  const appInfo = {
    pkg: { name, version, engines, dependencies, devDependencies },
    lastBuildTime: new Date().toISOString()
  };

  return {
    base: VITE_PUBLIC_PATH,
    root,
    resolve: {
      alias
    },
    plugins: [
      vue(),
      vueJsx(),
      svgLoader(),
      removeConsole(),
      viteCompression({
        deleteOriginFile: false,
        threshold: 5120,
        algorithm: "gzip",
        ext: ".gz"
      })
    ],
    server: {
      port: VITE_PORT,
      proxy: {
        "/api": {
          target: VITE_HOST_URL,
          changeOrigin: true,
          secure: false
        },
        "/avatar": {
          target: VITE_HOST_URL,
          changeOrigin: true,
          secure: false
        },
        "/upload": {
          target: VITE_HOST_URL,
          changeOrigin: true,
          secure: false
        },
        "/hub": {
          target: VITE_HOST_URL,
          changeOrigin: true,
          secure: false,
          ws: true
        }
      },
      // 预热文件以提前转换和缓存结果，降低启动期间的初始页面加载时长并防止转换瀑布
      warmup: {
        clientFiles: ["./index.html", "./src/{views,components}/*"]
      }
    },
    build: {
      target: "es2015",
      sourcemap: false,
      // 消除打包大小超过500kb警告
      chunkSizeWarningLimit: 4000,
      rollupOptions: {
        input: {
          index: pathResolve("./index.html", import.meta.url)
        },
        output: {
          chunkFileNames: "static/js/[name]-[hash].js",
          entryFileNames: "static/js/[name]-[hash].js",
          assetFileNames: "static/[ext]/[name]-[hash].[ext]"
        }
      }
    },
    define: {
      __APP_INFO__: JSON.stringify(appInfo)
    }
  };
});

/**
 * 根据可选的路径片段生成一个新的绝对路径
 *
 * @param dir 路径片段，默认'.'
 * @param importMetaUrl 模块的完整 'url'，如果在 '.' 目录外调用必传 'import.meta.url'
 * @returns 解析后的绝对路径
 */
function pathResolve(dir = ".", importMetaUrl = import.meta.url) {
  // 当前文件目录的绝对路径
  const currentFileDir = dirname(fileURLToPath(importMetaUrl));
  // 解析的绝对路径
  const resolvedPath = resolve(currentFileDir, dir);
  // 返回解析后的绝对路径
  return resolvedPath;
}

/**
 * 处理环境变量，将其转换为正确的类型
 *
 * @param envConf 环境变量配置对象
 * @returns 处理后的环境变量对象
 */
function wrapperEnv(envConf: Recordable): ViteEnv {
  // 默认值
  const ret: ViteEnv = {
    VITE_PORT: 8848,
    VITE_HOST_URL: "",
    VITE_PUBLIC_PATH: ""
  };

  for (const envName of Object.keys(envConf)) {
    let envVal = envConf[envName].replace(/\\n/g, "\n");
    envVal = envVal === "true" ? true : envVal === "false" ? false : envVal;

    if (envName === "VITE_PORT") {
      envVal = Number(envVal);
    }
    ret[envName] = envVal;

    if (typeof envVal === "string") {
      process.env[envName] = envVal;
    } else if (typeof envVal === "object") {
      process.env[envName] = JSON.stringify(envVal);
    }
  }
  return ret;
}
